
package jkCore.social.ad;

import android.app.Activity;
import android.content.pm.ApplicationInfo;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.ViewGroup;

import jkCore.social.ad.adapter.AdBaseAdapter;
import jkCore.social.ad.config.AdConfig;
import jkCore.utils.Utils;

import org.json.JSONObject;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

public class AdManager {

    public enum XAdInterShowConditionType {
        AWInterShowConditionTypeCount,
        AWInterShowConditionTypeRate
    }

    private static final String TOP_TAG = "AdManager";
    private static final String XADPlacementDefault = "XADPlacementDefault";
    private static final String AD_FIRST_INIT = "AD_FIRST_INIT";
    private static final String AD_REMOVE = "AD_REMOVE";

    private static final int MSG_AD_SHOW_BANNER = 112;
    private static final int MSG_AD_SHOW_NATIVE = 113;
    private static final int MSG_AD_SHOW_FLOAT = 114;
    private static final int MSG_AD_SHOW_BOX = 115;

    // 当前窗口
    private Activity mActivity;
    // 适配器列表
    private List<AdBaseAdapter> mAdapters;
    private StaticHandler mHandler;

    // 横幅
    private AdCallBack adBannerCallback;     // 回调
    private Timer mBannerTimer;              // timer
    private boolean isTryShowBanner = false; // 是否去显示横幅广告
    private boolean hasShowBanner = false;   // 是否正在显示横幅广告

    // 原生
    private AdCallBack adNativeCallback;
    private Timer mNativeTimer;
    private ViewGroup mNativeView;
    private boolean isTryShowNative = false;
    private boolean hasShowNative = false;

    // 插屏
    private AdCallBack adFloatCallback;
    private Timer mFloatTimer;
    private ViewGroup mFloatView;
    private boolean isTryShowFloat = false;
    private boolean hasShowFloat = false;

    // 矩形
    private AdCallBack adBoxCallback;
    private Timer mBoxTimer;
    private ViewGroup mBoxView;
    private boolean isTryShowBox = false;
    private boolean hasShowBox = false;
    private Map<String, Integer> interCacheCount = new HashMap<String, Integer>();

    public boolean splashShowed = false;
    private boolean isRemoveAds = false;
    private boolean hasFirstInit = false; // 是不是第一次初始化
    private boolean isPause = false;      // 暂停

    // 广告回调接口
    public interface AdCallBack {
        void onStart(JSONObject ret);  // 开始
        void onFinish(JSONObject ret); // 完成
        void onClick(JSONObject ret);  // 点击
    }

    private boolean isInit = false; // 是否初始化
    private boolean isDebug = false;// 是否debug
    private boolean is_zh_Hans;     // 是否中文

    private static AdManager _ins;

    public static AdManager ins() {
        if (_ins == null) {
            _ins = new AdManager();
            _ins.mAdapters = new ArrayList<AdBaseAdapter>();
        }
        return _ins;
    }

    // 添加一个适配器
    public void addAdapter(AdBaseAdapter adapter) {
        mAdapters.add(adapter);
    }

    // 设置为debug模式
    public void setDebug(boolean debug) {
        isDebug = debug;
    }

    // 初始化适配器
    public void initAd(Activity activity, String appKey) {
        if (isDebug) {
            Log.i(TOP_TAG, "initAd : " + appKey);
        }
        if (isInit || appKey == null || appKey.isEmpty()) {
            return;
        }
        this.mActivity = activity;
        // 获取应用信息
        ApplicationInfo info = this.mActivity.getApplicationInfo();
        // 是不是debug模式
        this.isDebug = (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
        this.isRemoveAds = Boolean.parseBoolean(Utils.loadDataforKey(mActivity, AD_REMOVE));
        this.hasFirstInit = Boolean.parseBoolean(Utils.loadDataforKey(mActivity, AD_FIRST_INIT));
        String currentLanguage = Locale.getDefault().toString();
        is_zh_Hans = currentLanguage.contains("zh_CN") || currentLanguage.contains("Hans");
        mHandler = new StaticHandler(this);
        AdConfig.getIns().requestConfig(mActivity, appKey, mAdapters);
        initAllAds();
        if (isDebug) {
            Log.i(TOP_TAG, "initAd Finish - HasFirstInit:" + hasFirstInit + " RemoveAds:" + isRemoveAds);
        }
        if (!this.hasFirstInit) {
            this.hasFirstInit = true;
            Utils.saveDataforKey(mActivity, "AD_FIRST_INIT", this.hasFirstInit + "");
        }
    }



    // 从弱引用对象获取一个adManager
    private static class StaticHandler extends Handler {
        private final WeakReference<AdManager> weakReference;

        public StaticHandler(AdManager adManager) {
            this.weakReference = new WeakReference<>(adManager);
        }

        @Override
        public void handleMessage(Message msg) {
            AdManager adManager = weakReference.get();
            super.handleMessage(msg);
            if (adManager != null) {
                switch (msg.what) {
                    case MSG_AD_SHOW_BANNER:
                        adManager.tryShowBanner();
                        break;
                    case MSG_AD_SHOW_NATIVE:
                        adManager.tryShowNative();
                        break;
                    case MSG_AD_SHOW_FLOAT:
                        adManager.tryShowFloat();
                        break;
                    case MSG_AD_SHOW_BOX:
                        adManager.tryShowBox();
                        break;
                    default:
                        break;
                }
            }
        }
    }

    // 初始化所有的适配器
    private void initAllAds() {
        if (mAdapters == null) {
            return;
        }
        for (AdBaseAdapter adapter : mAdapters) {
            adapter.setDebug(isDebug);
            adapter.setRemoveAds(isRemoveAds);
            adapter.initAd(mActivity);
            if (hasFirstInit) {
                adapter.loadSplashAds();
            }
        }
        isInit = true;
        // 加载横幅广告、插屏广告、激励视频广告、原生广告、悬浮广告
        loadBannerAds();
        loadInterAds();
        loadRewardAds();
        loadNativeAds();
        loadFloatAds();
        loadBoxAds();
    }

    /*******************横幅广告******************************/

    public boolean isBannerReady() {
        if (isDebug) {
            Log.i(TOP_TAG, "isBannerReady");
        }
        if (!isInit) {
            return false;
        }
        for (AdBaseAdapter adapter : mAdapters) {
            if (adapter.isBannerReady()) {
                return true;
            }
        }
        return false;
    }

    public void showBanner(AdCallBack callBack) {
        if (isDebug) {
            Log.i(TOP_TAG, "showBanner");
        }
        if (!isInit || isTryShowBanner || hasShowBanner) {
            return;
        }
        stopTryShowBanner();
        isTryShowBanner = true;
        adBannerCallback = callBack;
        mBannerTimer = new Timer();
        mBannerTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                // 获取一个Message池对象 msg。what用来存数字类型
                Message msg = Message.obtain();
                msg.what = MSG_AD_SHOW_BANNER;
                mHandler.sendMessage(msg);
            }
        }, 0, AdConfig.BANNER_REQUEST_INTERVAL);
    }

    // tryShowBanner
    private void tryShowBanner() {
        if (isPause) {
            return;
        }
        if (isDebug) {
            Log.i(TOP_TAG, "tryShowBanner");
        }
        if (!isTryShowBanner || hasShowBanner) {
            stopTryShowBanner();
            return;
        }
        Collections.sort(mAdapters, new Comparator<AdBaseAdapter>() {
            @Override
            public int compare(AdBaseAdapter lAdapter, AdBaseAdapter rAdapter) {
                if (is_zh_Hans) {
                    int l = lAdapter.isOut() ? 1 : 0;
                    int r = rAdapter.isOut() ? 1 : 0;
                    if (l != r) {
                        return l - r;
                    }
                }
                return lAdapter.mConfigValue.bannerPriority - rAdapter.mConfigValue.bannerPriority;
            }
        });
        for (AdBaseAdapter adapter : mAdapters) {
            if (adapter.isBannerReady()) {
                hasShowBanner = true;
                stopTryShowBanner();
                adapter.showBanner(adBannerCallback);
                break;
            }
        }
    }

    // 隐藏所有横幅广告
    public void hideBanner() {
        if (isDebug) {
            Log.i(TOP_TAG, "hideBanner");
        }
        stopTryShowBanner();
        if (!isInit) {
            return;
        }
        hasShowBanner = false;
        for (AdBaseAdapter adapter : mAdapters) {
            adapter.hideBanner();
        }
    }

    // 停止try显示横幅广告
    private void stopTryShowBanner() {
        if (isDebug) {
            Log.i(TOP_TAG, "stopTryShowBanner");
        }
        isTryShowBanner = false;
        if (mBannerTimer != null) {
            mBannerTimer.cancel();
            mBannerTimer = null;
        }
    }

    /*******************插屏广告******************************/

    public boolean isInterReady() {
        if (isDebug) {
            Log.i(TOP_TAG, "isInterReady");
        }
        if (!isInit) {
            return false;
        }
        for (AdBaseAdapter adapter : mAdapters) {
            if (adapter.isInterReady()) {
                return true;
            }
        }
        return false;
    }

    public void showInter(String placement, AdCallBack callBack) {
        if (placement == null || placement.isEmpty()) {
            placement = XADPlacementDefault;
        }
        boolean isShowSplash = placement.equalsIgnoreCase("splash");
        if (isDebug) {
            Log.i(TOP_TAG, "showInter:" + placement);
        }
        if (!isInit) {
            return;
        }
        boolean canShow = false;
        try {
            JSONObject pdata = AdConfig.getIns().interParams.optJSONObject(placement);
            if (pdata == null) {
                placement = XADPlacementDefault;
            }
            XAdInterShowConditionType iType = XAdInterShowConditionType.AWInterShowConditionTypeCount;
            int iParam = 1;
            int iCount = 0;
            if (pdata == null) {
                pdata = AdConfig.getIns().interParams.optJSONObject(placement);
            }
            if (pdata != null) {
                iType = XAdInterShowConditionType.values()[pdata.optInt("Type") - 1];
                iParam = pdata.optInt("Param", 2);
            }
            if (iType == XAdInterShowConditionType.AWInterShowConditionTypeCount) {
                if (interCacheCount.containsKey(placement)) {
                    iCount = interCacheCount.get(placement);
                }
                iCount += 1;
                if (iCount >= iParam) {
                    canShow = true;
                    iCount = 0;
                }
                interCacheCount.put(placement, iCount);
            } else if (iType == XAdInterShowConditionType.AWInterShowConditionTypeRate) {
                iCount = new Random().nextInt(100);
                if (iCount <= iParam) {
                    canShow = true;
                }
            }
            if (isDebug) {
                Log.i(TOP_TAG, "showInter:" + placement + " Type:" + iType + " Param:" + iParam + " Count:" + iCount + " CanShow:" + canShow);
            }
        } catch (Exception e) {
            e.printStackTrace();
            canShow = true;
            if (isDebug) {
                Log.i(TOP_TAG, "showInter exception error:" + placement + " CanShow: true");
            }
        }
        if (canShow) {
            Collections.sort(mAdapters, new Comparator<AdBaseAdapter>() {
                @Override
                public int compare(AdBaseAdapter lAdapter, AdBaseAdapter rAdapter) {
                    if (is_zh_Hans) {
                        int l = lAdapter.isOut() ? 1 : 0;
                        int r = rAdapter.isOut() ? 1 : 0;
                        if (l != r) {
                            return l - r;
                        }
                    }
                    return lAdapter.mConfigValue.interPriority - rAdapter.mConfigValue.interPriority;
                }
            });
            if (isShowSplash) {
                for (AdBaseAdapter adapter : mAdapters) {
                    if (adapter.isSplashReady()) {
                        adapter.showSplash(callBack);
                        return;
                    }
                }
            }
            for (AdBaseAdapter adapter : mAdapters) {
                if (adapter.isInterReady()) {
                    adapter.showInter(callBack);
                    break;
                }
            }
        }
    }

    /*******************激励广告******************************/

    public boolean isVideoReady() {
        if (isDebug) {
            Log.i(TOP_TAG, "isVideoReady");
        }
        if (!isInit) {
            return false;
        }
        for (AdBaseAdapter adapter : mAdapters) {
            if (adapter.isVideoReady()) {
                return true;
            }
        }
        return false;
    }

    public void showVideo(String placement, AdCallBack callBack) {
        if (placement == null || placement.isEmpty()) {
            placement = XADPlacementDefault;
        }
        if (isDebug) {
            Log.i(TOP_TAG, "showVideo:" + placement);
        }
        if (!isInit) {
            return;
        }
        Collections.sort(mAdapters, new Comparator<AdBaseAdapter>() {
            @Override
            public int compare(AdBaseAdapter lAdapter, AdBaseAdapter rAdapter) {
                if (is_zh_Hans) {
                    int l = lAdapter.isOut() ? 1 : 0;
                    int r = rAdapter.isOut() ? 1 : 0;
                    if (l != r) {
                        return l - r;
                    }
                }
                return lAdapter.mConfigValue.videoPriority - rAdapter.mConfigValue.videoPriority;
            }
        });
        for (AdBaseAdapter adapter : mAdapters) {
            if (adapter.isVideoReady()) {
                adapter.showVideo(callBack);
                break;
            }
        }
    }

    /*******************原生广告******************************/

    public void showNative(ViewGroup view, AdCallBack callBack) {
        if (isDebug) {
            Log.i(TOP_TAG, "showNative");
        }
        if (!isInit || mNativeView != null || hasShowNative) {
            return;
        }
        stopTryShowNative();
        isTryShowNative = true;
        mNativeView = view;
        adNativeCallback = callBack;
        mNativeTimer = new Timer();
        mNativeTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                Message msg = Message.obtain();
                msg.what = MSG_AD_SHOW_NATIVE;
                mHandler.sendMessage(msg);
            }
        }, 0, 1000);
    }

    private void tryShowNative() {
        if (isPause) {
            return;
        }
        if (isDebug) {
            Log.i(TOP_TAG, "tryShowNative");
        }
        if (!isTryShowNative || mNativeView == null || hasShowNative) {
            stopTryShowNative();
            return;
        }
        Collections.sort(mAdapters, new Comparator<AdBaseAdapter>() {
            @Override
            public int compare(AdBaseAdapter lAdapter, AdBaseAdapter rAdapter) {
                if (is_zh_Hans) {
                    int l = lAdapter.isOut() ? 1 : 0;
                    int r = rAdapter.isOut() ? 1 : 0;
                    if (l != r) {
                        return l - r;
                    }
                }
                return lAdapter.mConfigValue.nativePriority - rAdapter.mConfigValue.nativePriority;
            }
        });
        for (AdBaseAdapter adapter : mAdapters) {
            if (adapter.isNativeReady()) {
                hasShowNative = true;
                stopTryShowNative();
                adapter.showNative(mNativeView, adNativeCallback);
                break;
            }
        }
    }

    public void hideNative() {
        if (isDebug) {
            Log.i(TOP_TAG, "hideNative");
        }
        mNativeView = null;
        stopTryShowNative();
        if (!isInit) {
            return;
        }
        hasShowNative = false;
        for (AdBaseAdapter adapter : mAdapters) {
            adapter.hideNative();
        }
    }

    private void stopTryShowNative() {
        if (isDebug) {
            Log.i(TOP_TAG, "stopTryShowNative");
        }
        isTryShowNative = false;
        if (mNativeTimer != null) {
            mNativeTimer.cancel();
            mNativeTimer = null;
        }
    }

    /*******************浮动广告******************************/

    public void showFloat(ViewGroup view, AdCallBack callBack) {
        if (isDebug) {
            Log.i(TOP_TAG, "showFloat");
        }
        if (!isInit || mFloatView != null || hasShowFloat) {
            return;
        }
        stopTryShowFloat();
        isTryShowFloat = true;
        mFloatView = view;
        adFloatCallback = callBack;
        mFloatTimer = new Timer();
        mFloatTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                Message msg = Message.obtain();
                msg.what = MSG_AD_SHOW_FLOAT;
                mHandler.sendMessage(msg);
            }
        }, 0, 1000);
    }

    private void tryShowFloat() {
        if (isPause) {
            return;
        }
        if (isDebug) {
            Log.i(TOP_TAG, "tryShowFloat");
        }
        if (!isTryShowFloat || mFloatView == null || hasShowFloat) {
            stopTryShowFloat();
            return;
        }
        Collections.sort(mAdapters, new Comparator<AdBaseAdapter>() {
            @Override
            public int compare(AdBaseAdapter lAdapter, AdBaseAdapter rAdapter) {
                if (is_zh_Hans) {
                    int l = lAdapter.isOut() ? 1 : 0;
                    int r = rAdapter.isOut() ? 1 : 0;
                    if (l != r) {
                        return l - r;
                    }
                }
                return lAdapter.mConfigValue.floatPriority - rAdapter.mConfigValue.floatPriority;
            }
        });
        for (AdBaseAdapter adapter : mAdapters) {
            if (adapter.isFloatReady()) {
                hasShowFloat = true;
                stopTryShowFloat();
                adapter.showFloat(mFloatView, adFloatCallback);
                break;
            }
        }
    }

    public void hideFloat() {
        if (isDebug) {
            Log.i(TOP_TAG, "hideFloat");
        }
        mFloatView = null;
        stopTryShowFloat();
        if (!isInit) {
            return;
        }
        hasShowFloat = false;
        for (AdBaseAdapter adapter : mAdapters) {
            adapter.hideFloat();
        }
    }

    private void stopTryShowFloat() {
        if (isDebug) {
            Log.i(TOP_TAG, "stopTryShowFloat");
        }
        isTryShowFloat = false;
        if (mFloatTimer != null) {
            mFloatTimer.cancel();
            mFloatTimer = null;
        }
    }

    /*******************矩形广告******************************/

    public void showBox(ViewGroup view, AdCallBack callBack) {
        if (isDebug) {
            Log.i(TOP_TAG, "showBox");
        }
        if (!isInit || mBoxView != null || hasShowBox) {
            return;
        }
        stopTryShowBox();
        isTryShowBox = true;
        mBoxView = view;
        adBoxCallback = callBack;
        mBoxTimer = new Timer();
        mBoxTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                Message msg = Message.obtain();
                msg.what = MSG_AD_SHOW_BOX;
                mHandler.sendMessage(msg);
            }
        }, 0, 1000);
    }

    private void tryShowBox() {
        if (isPause) {
            return;
        }
        if (isDebug) {
            Log.i(TOP_TAG, "tryShowBox");
        }
        if (!isTryShowBox || mBoxView == null || hasShowBox) {
            stopTryShowBox();
            return;
        }
        Collections.sort(mAdapters, new Comparator<AdBaseAdapter>() {
            @Override
            public int compare(AdBaseAdapter lAdapter, AdBaseAdapter rAdapter) {
                if (is_zh_Hans) {
                    int l = lAdapter.isOut() ? 1 : 0;
                    int r = rAdapter.isOut() ? 1 : 0;
                    if (l != r) {
                        return l - r;
                    }
                }
                return lAdapter.mConfigValue.boxPriority - rAdapter.mConfigValue.boxPriority;
            }
        });
        for (AdBaseAdapter adapter : mAdapters) {
            if (adapter.isBoxReady()) {
                hasShowBox = true;
                stopTryShowBox();
                adapter.showBox(mBoxView, adBoxCallback);
                break;
            }
        }
    }

    public void hideBox() {
        if (isDebug) {
            Log.i(TOP_TAG, "hideBox");
        }
        mBoxView = null;
        stopTryShowBox();
        if (!isInit) {
            return;
        }
        hasShowBox = false;
        for (AdBaseAdapter adapter : mAdapters) {
            adapter.hideBox();
        }
    }

    private void stopTryShowBox() {
        if (isDebug) {
            Log.i(TOP_TAG, "stopTryShowBox");
        }
        isTryShowBox = false;
        if (mBoxTimer != null) {
            mBoxTimer.cancel();
            mBoxTimer = null;
        }
    }

    // 键盘按下
    public boolean onKeyDown(int keyCode, KeyEvent keyEvent) {
        if (isDebug) {
            Log.i(TOP_TAG, "onKeyDown : " + keyCode);
        }
        boolean isKeyDown = false;
        for (AdBaseAdapter adapter : mAdapters) {
            isKeyDown |= adapter.onKeyDown(keyCode, keyEvent);
        }
        return isKeyDown;
    }

    // 恢复
    public void onResume() {
        if (isDebug) {
            Log.i(TOP_TAG, "onResume");
        }
        for (AdBaseAdapter adapter : mAdapters) {
            adapter.onResume();
        }
        isPause = false;
    }

    // 暂停
    public void onPause() {
        if (isDebug) {
            Log.i(TOP_TAG, "onPause");
        }
        for (AdBaseAdapter adapter : mAdapters) {
            adapter.onPause();
        }
        isPause = true;
    }

    // 销毁
    public void onDestroy() {
        if (isDebug) {
            Log.i(TOP_TAG, "onDestroy");
        }
        for (AdBaseAdapter adapter : mAdapters) {
            adapter.onDestroy();
        }
    }

    // 加载横幅广告
    private void loadBannerAds() {
        if (isDebug) {
            Log.i(TOP_TAG, "loadBannerAds");
        }
        if (!isInit) {
            return;
        }
        for (AdBaseAdapter adapter : mAdapters) {
            adapter.loadBannerAds();
        }
        if (isTryShowBanner) {
            showBanner(adBannerCallback);
        }
    }

    private void loadInterAds() {
        if (isDebug) {
            Log.i(TOP_TAG, "loadInterAds");
        }
        if (!isInit) {
            return;
        }
        for (AdBaseAdapter adapter : mAdapters) {
            adapter.loadInterAds();
        }
    }

    private void loadRewardAds() {
        if (isDebug) {
            Log.i(TOP_TAG, "loadRewardAds");
        }
        if (!isInit) {
            return;
        }
        for (AdBaseAdapter adapter : mAdapters) {
            adapter.loadRewardAds();
        }
    }

    private void loadNativeAds() {
        if (isDebug) {
            Log.i(TOP_TAG, "loadNativeAds");
        }
        if (!isInit) {
            return;
        }
        for (AdBaseAdapter adapter : mAdapters) {
            adapter.loadNativeAds();
        }
        if (isTryShowNative && mNativeView != null) {
            showNative(mNativeView, adNativeCallback);
        }
    }

    private void loadFloatAds() {
        if (isDebug) {
            Log.i(TOP_TAG, "loadFloatAds");
        }
        if (!isInit) {
            return;
        }
        for (AdBaseAdapter adapter : mAdapters) {
            adapter.loadFloatAds();
        }
        if (isTryShowFloat && mFloatView != null) {
            showFloat(mFloatView, adFloatCallback);
        }
    }

    private void loadBoxAds() {
        if (isDebug) {
            Log.i(TOP_TAG, "loadBoxAds");
        }
        if (!isInit) {
            return;
        }
        for (AdBaseAdapter adapter : mAdapters) {
            adapter.loadBoxAds();
        }
        if (isTryShowBox && mBoxView != null) {
            showBox(mBoxView, adBoxCallback);
        }
    }

//    public void fetchAppLinkData(Utils.CommonCallback<JSONObject> callback) {
//        JSONObject ret = new JSONObject();
//        AtomicInteger count = new AtomicInteger(mAdapters.size());
//        for (AdBaseAdapter adapter : mAdapters) {
//            adapter.fetchAppLinkData(new Utils.CommonCallback<JSONObject>() {
//                @Override
//                public void invoke(JSONObject data) {
//                    if (data != null) {
//                        try {
//                            for (Iterator<String> it = data.keys(); it.hasNext(); ) {
//                                String key = it.next();
//                                ret.put(key, data.get(key));
//                            }
//                        } catch (JSONException ignored) {
//                        }
//                    }
//                    int c = count.decrementAndGet();
//                    if (c == 0) {
//                        callback.invoke(ret);
//                    }
//                }
//            });
//        }
//    }
}
